package github.nisrulz.projecteasydeviceinfo.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.security.SystemPermission;
import ohos.sensor.bean.CategoryBody;
import ohos.sensor.bean.CategoryEnvironment;
import ohos.sensor.bean.CategoryLight;
import ohos.sensor.bean.CategoryMotion;
import ohos.sensor.bean.CategoryOrientation;
import ohos.sensor.bean.CategoryOther;
import ohos.telephony.RadioInfoManager;
import ohos.telephony.SimInfoManager;
import ohos.utils.LightweightMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import github.nisrulz.easydeviceinfo.base.BatteryHealth;
import github.nisrulz.easydeviceinfo.base.ChargingVia;
import github.nisrulz.easydeviceinfo.base.DeviceType;
import github.nisrulz.easydeviceinfo.base.EasyAppMod;
import github.nisrulz.easydeviceinfo.base.EasyBatteryMod;
import github.nisrulz.easydeviceinfo.base.EasyConfigMod;
import github.nisrulz.easydeviceinfo.base.EasyDeviceMod;
import github.nisrulz.easydeviceinfo.base.EasyDisplayMod;
import github.nisrulz.easydeviceinfo.base.EasyFingerprintMod;
import github.nisrulz.easydeviceinfo.base.EasyIdMod;
import github.nisrulz.easydeviceinfo.base.EasyLocationMod;
import github.nisrulz.easydeviceinfo.base.EasyMemoryMod;
import github.nisrulz.easydeviceinfo.base.EasyNetworkMod;
import github.nisrulz.easydeviceinfo.base.EasyNfcMod;
import github.nisrulz.easydeviceinfo.base.EasySensorMod;
import github.nisrulz.easydeviceinfo.base.EasySimMod;
import github.nisrulz.easydeviceinfo.base.NetworkType;
import github.nisrulz.easydeviceinfo.base.OrientationType;
import github.nisrulz.easydeviceinfo.base.RingerMode;
import github.nisrulz.easydeviceinfo.common.EasyDeviceInfo;
import github.nisrulz.projecteasydeviceinfo.BuildConfig;
import github.nisrulz.projecteasydeviceinfo.ResourceTable;

public class MainAbilitySlice extends AbilitySlice {
    private SampleItemProvider sampleItemProvider;
    private HiLogLabel La = new HiLogLabel(HiLog.LOG_APP, 0011, "my");

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        // Data Array List of Info Object
        final ArrayList<String> data = new ArrayList<>();

        // Add Data
        LightweightMap<String, String> deviceDataMap = new LightweightMap<String, String>();

        // Setup the value to be returned when result is either not found or invalid/null
        EasyDeviceInfo.setNotFoundVal("na");
        // Enable Debugging when in Debug build
        if (BuildConfig.DEBUG) {
            EasyDeviceInfo.debug();
        }
        // Library Info

        // ID Mod
        EasyIdMod easyIdMod = new EasyIdMod(this);
        String[] emailIds = easyIdMod.getAccounts();
        StringBuilder emailString = new StringBuilder();
        if (emailIds != null && emailIds.length > 0) {
            for (String e : emailIds) {
                emailString.append(e).append("\n");
            }
        } else {
            emailString.append("-");
        }
        EasyConfigMod easyConfigMod = new EasyConfigMod(this);
        deviceDataMap.put("Time (ms)", String.valueOf(easyConfigMod.getTime()));
        deviceDataMap.put("Formatted Time (24Hrs)", easyConfigMod.getFormattedTime());
        deviceDataMap.put("UpTime (ms)", String.valueOf(easyConfigMod.getUpTime()));
        deviceDataMap.put("Formatted Up Time (24Hrs)", easyConfigMod.getFormattedUpTime());
        deviceDataMap.put("Date", String.valueOf(easyConfigMod.getCurrentDate()));
        deviceDataMap.put("Formatted Date", easyConfigMod.getFormattedDate());
        deviceDataMap.put("SD Card available", String.valueOf(easyConfigMod.hasSdCard()));

        @RingerMode int ringermode = easyConfigMod.getDeviceRingerMode();
        switch (ringermode) {
            case RingerMode.NORMAL:
                deviceDataMap.put(getString(ResourceTable.String_ringer_mode), "normal");
                break;
            case RingerMode.VIBRATE:
                deviceDataMap.put(getString(ResourceTable.String_ringer_mode), "vibrate");
                break;
            case RingerMode.SILENT:
            default:
                deviceDataMap.put(getString(ResourceTable.String_ringer_mode), "silent");
                break;
        }
        // Fingerprint Mod
        EasyFingerprintMod easyFingerprintMod = new EasyFingerprintMod(getAbility());
        deviceDataMap.put("Is Fingerprint Sensor present?", String.valueOf(easyFingerprintMod.isFingerprintSensorPresent()));

        // Sensor Mod
        EasySensorMod easySensorMod = new EasySensorMod();
        ArrayList list = (ArrayList) easySensorMod.getAllSensors();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) instanceof CategoryOther) {
                CategoryOther sensorData = (CategoryOther) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            } else if (list.get(i) instanceof CategoryOrientation) {
                CategoryOrientation sensorData = (CategoryOrientation) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            } else if (list.get(i) instanceof CategoryMotion) {
                CategoryMotion sensorData = (CategoryMotion) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            } else if (list.get(i) instanceof CategoryLight) {
                CategoryLight sensorData = (CategoryLight) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            } else if (list.get(i) instanceof CategoryEnvironment) {
                CategoryEnvironment sensorData = (CategoryEnvironment) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            } else if (list.get(i) instanceof CategoryBody) {
                CategoryBody sensorData = (CategoryBody) list.get(i);
                String stringBuilder = "\nVendor : "
                    + sensorData.getVendor()
                    + "\n"
                    + "Version : "
                    + sensorData.getVersion()
                    + "\n"
                    + "Resolution : "
                    + sensorData.getResolution()
                    + "\n"
                    + "Max Range : "
                    + sensorData.getUpperRange();
                deviceDataMap.put("Sensor Name - " + sensorData.getName(), stringBuilder);
            }
        }

        // SIM Mod
        EasySimMod easySimMod = new EasySimMod(this);
        deviceDataMap.put("SIM Serial Number", easySimMod.getSIMSerial());
        deviceDataMap.put("Country", easySimMod.getCountry());
        deviceDataMap.put("Carrier", easySimMod.getCarrier());
        deviceDataMap.put("SIM Network Locked", String.valueOf(easySimMod.isSimNetworkLocked()));
        deviceDataMap.put("Is Multi SIM", String.valueOf(easySimMod.isMultiSim()));
        deviceDataMap.put("Number of active SIM", String.valueOf(easySimMod.getNumberOfActiveSim()));
        if (easySimMod.isMultiSim()) {
            List<Integer> activeMultiSimInfo = easySimMod.getActiveMultiSimInfo();
            if (activeMultiSimInfo != null) {
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < activeMultiSimInfo.size(); i++) {
                    Integer slotId = activeMultiSimInfo.get(i);
                    stringBuilder.append("\nSIM ")
                        .append(i)
                        .append(" Info")
                        .append("\nPhone Number :")
                        .append(SimInfoManager.getInstance(this).getSimIccId(slotId))
                        .append("\n")
                        .append("Carrier Name :")
                        .append(RadioInfoManager.getInstance(this).getNetworkState(slotId).getLongOperatorName())
                        .append("\n")
                        .append("Country :")
                        .append(SimInfoManager.getInstance(this).getIsoCountryCodeForSim(slotId))
                        .append("\n")
                        .append("Roaming :")
                        .append(RadioInfoManager.getInstance(this).getNetworkState(slotId).isRoaming())
                        .append("\n");
                }
                deviceDataMap.put("Multi SIM Info", stringBuilder.toString());
            }
        }

        // Device Mod
        EasyDeviceMod easyDeviceMod = new EasyDeviceMod(this);
        deviceDataMap.put("Language", easyDeviceMod.getLanguage());
        deviceDataMap.put("IMEI", easyDeviceMod.getIMEI());
        deviceDataMap.put("User-Agent", easyIdMod.getUA());
        deviceDataMap.put("Model", easyDeviceMod.getModel());
        deviceDataMap.put("OS Codename", easyDeviceMod.getOSCodename());
        deviceDataMap.put("OS Version", easyDeviceMod.getOSVersion());
        deviceDataMap.put("Phone Number", easyDeviceMod.getPhoneNo());
        deviceDataMap.put("Product", easyDeviceMod.getProduct());
        deviceDataMap.put("Device Rooted", String.valueOf(easyDeviceMod.isDeviceRooted()));
        deviceDataMap.put("Screen Display ID", easyDeviceMod.getScreenDisplayID());
        deviceDataMap.put("Build Version SDK", String.valueOf(easyDeviceMod.getBuildVersionSDK()));

        @DeviceType int deviceType = easyDeviceMod.getDeviceType(getAbility());
        switch (deviceType) {
            case DeviceType.WATCH:
                deviceDataMap.put(getString(ResourceTable.String_device_type), "watch");
                break;
            case DeviceType.PHONE:
                deviceDataMap.put(getString(ResourceTable.String_device_type), "phone");
                break;
            case DeviceType.PHABLET:
                deviceDataMap.put(getString(ResourceTable.String_device_type), "phablet");
                break;
            case DeviceType.TABLET:
                deviceDataMap.put(getString(ResourceTable.String_device_type), "tablet");
                break;
            case DeviceType.TV:
                deviceDataMap.put(getString(ResourceTable.String_device_type), "tv");
                break;
        }

        @OrientationType int orientationType = easyDeviceMod.getOrientation(getAbility());
        switch (orientationType) {
            case OrientationType.LANDSCAPE:
                deviceDataMap.put(getString(ResourceTable.String_orientation), "Landscape");
                break;
            case OrientationType.PORTRAIT:
                deviceDataMap.put(getString(ResourceTable.String_orientation), "Portrait");
                break;
            case OrientationType.UNKNOWN:
            default:
                deviceDataMap.put(getString(ResourceTable.String_orientation), "Unknown");
                break;
        }

        // App Mod
        EasyAppMod easyAppMod = new EasyAppMod(this);
        deviceDataMap.put("App Name", getString(ResourceTable.String_app_name));
        deviceDataMap.put("Package Name", easyAppMod.getPackageName());
        deviceDataMap.put("Ability Name", easyAppMod.getAbilityName());
        deviceDataMap.put("App version", easyAppMod.getAppVersion());
        deviceDataMap.put("App versioncode", easyAppMod.getAppVersionCode());
        deviceDataMap.put("Does app have Camera permission?",
            String.valueOf(easyAppMod.isPermissionGranted(SystemPermission.CAMERA)));

        // Network Mod
        EasyNetworkMod easyNetworkMod = new EasyNetworkMod(this);
        deviceDataMap.put("WIFI MAC Address", easyNetworkMod.getWifiMAC());
        deviceDataMap.put("WIFI LinkSpeed", easyNetworkMod.getWifiLinkSpeed());
        deviceDataMap.put("WIFI SSID", easyNetworkMod.getWifiSSID());
        deviceDataMap.put("WIFI BSSID", easyNetworkMod.getWifiBSSID());
        deviceDataMap.put("IPv4 Address", easyNetworkMod.getIPv4Address());
        deviceDataMap.put("IPv6 Address", easyNetworkMod.getIPv6Address());
        deviceDataMap.put("Network Available", String.valueOf(easyNetworkMod.isNetworkAvailable()));
        deviceDataMap.put("Wi-Fi enabled", String.valueOf(easyNetworkMod.isWifiEnabled()));

        @NetworkType int networkType = easyNetworkMod.getNetworkType();

        switch (networkType) {
            case NetworkType.CELLULAR_UNKNOWN:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular Unknown");
                break;
            case NetworkType.CELLULAR_UNIDENTIFIED_GEN:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular Unidentified Generation");
                break;
            case NetworkType.CELLULAR_2G:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular 2G");
                break;
            case NetworkType.CELLULAR_3G:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular 3G");
                break;
            case NetworkType.CELLULAR_4G:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular 4G");
                break;
            case NetworkType.WIFI_WIFIMAX:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Wifi/WifiMax");
                break;
            case NetworkType.CELLULAR_5G:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Cellular 5G");
                break;
            case NetworkType.UNKNOWN:
            default:
                deviceDataMap.put(getString(ResourceTable.String_network_type), "Unknown");
                break;
        }

        // Battery Mod
        EasyBatteryMod easyBatteryMod = new EasyBatteryMod(this);
        deviceDataMap.put("Battery Percentage",
            String.valueOf(easyBatteryMod.getBatteryPercentage()) + "%");
        deviceDataMap.put("Is device charging", String.valueOf(easyBatteryMod.isDeviceCharging()));
        easyBatteryMod.isBatteryPresent(new EasyBatteryMod.BatteryCallback() {
            @Override
            public void onSuccess(boolean isBatteryPresent) {
                data.add(data.size(), "Battery present : " + isBatteryPresent);
                if (sampleItemProvider != null) {
                    sampleItemProvider.notifyDataSetItemRangeChanged(0, data.size());
                }
            }
        });

        deviceDataMap.put("Battery technology", String.valueOf(easyBatteryMod.getBatteryTechnology()));
        deviceDataMap.put("Battery temperature",
            String.valueOf(easyBatteryMod.getBatteryTemperature()) + " deg C");
        deviceDataMap.put("Battery voltage",
            String.valueOf(easyBatteryMod.getBatteryVoltage()) + " mV");

        @BatteryHealth int batteryHealth = easyBatteryMod.getBatteryHealth();
        switch (batteryHealth) {
            case BatteryHealth.GOOD:
                deviceDataMap.put("Battery health", "Good");
                break;
            case BatteryHealth.HAVING_ISSUES:
            default:
                deviceDataMap.put("Battery health", "Having issues");
                break;
        }

        @ChargingVia int isChargingVia = easyBatteryMod.getChargingSource();
        switch (isChargingVia) {
            case ChargingVia.AC:
                deviceDataMap.put(getString(ResourceTable.String_device_charging_via), "AC");
                break;
            case ChargingVia.USB:
                deviceDataMap.put(getString(ResourceTable.String_device_charging_via), "USB");
                break;
            case ChargingVia.WIRELESS:
                deviceDataMap.put(getString(ResourceTable.String_device_charging_via), "Wireless");
                break;
            case ChargingVia.UNKNOWN_SOURCE:
            default:
                deviceDataMap.put(getString(ResourceTable.String_device_charging_via), "Unknown Source");
                break;
        }

        // Display Mod
        EasyDisplayMod easyDisplayMod = new EasyDisplayMod(this);
        deviceDataMap.put("Display Resolution", easyDisplayMod.getResolution());
        deviceDataMap.put("Screen Density", easyDisplayMod.getDensity());
        deviceDataMap.put("Screen Size", String.valueOf(easyDisplayMod.getPhysicalSize()));
        deviceDataMap.put("Email ID", emailString.toString());

        // Location Mod
        EasyLocationMod easyLocationMod = new EasyLocationMod(this);
        double[] l = easyLocationMod.getLatLong();
        String lat = String.valueOf(l[0]);
        String lon = String.valueOf(l[1]);
        deviceDataMap.put("Latitude", lat);
        deviceDataMap.put("Longitude", lon);
        // Memory Mod
        EasyMemoryMod easyMemoryMod = new EasyMemoryMod(this);
        deviceDataMap.put("Total RAM",
            String.valueOf(easyMemoryMod.convertToGb(easyMemoryMod.getTotalRAM())) + " Gb");
        deviceDataMap.put("Available Internal Memory",
            String.valueOf(easyMemoryMod.convertToGb(easyMemoryMod.getAvailableInternalMemorySize()))
                + " Gb");
        deviceDataMap.put("Available External Memory",
            String.valueOf(easyMemoryMod.convertToGb(easyMemoryMod.getAvailableExternalMemorySize()))
                + " Gb");
        deviceDataMap.put("Total Internal Memory",
            String.valueOf(easyMemoryMod.convertToGb(easyMemoryMod.getTotalInternalMemorySize()))
                + " Gb");
        deviceDataMap.put("Total External memory",
            String.valueOf(easyMemoryMod.convertToGb(easyMemoryMod.getTotalExternalMemorySize()))
                + " Gb");

        // NFC Mod
        EasyNfcMod easyNfcMod = new EasyNfcMod(this);
        deviceDataMap.put("is NFC present", String.valueOf(easyNfcMod.isNfcPresent()));
        deviceDataMap.put("is NFC enabled", String.valueOf(easyNfcMod.isNfcEnabled()));

        for (String key : deviceDataMap.keySet()) {
            data.add(key + " : " + deviceDataMap.get(key));
        }
        ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_list);
        listContainer.enableScrollBar(Component.VERTICAL, true);
        listContainer.setScrollbarColor(new Color(Color.getIntColor("#999999")));
        sampleItemProvider = new SampleItemProvider(data);
        listContainer.setItemProvider(sampleItemProvider);
    }

    /**
     * ListContainer 数据源
     *
     * @since 2021-04-01
     */
    class SampleItemProvider extends BaseItemProvider {
        private List<String> list;

        SampleItemProvider(List<String> list) {
            this.list = list;
        }

        @Override
        public int getCount() {
            return list == null ? 0 : list.size();
        }

        @Override
        public Object getItem(int position) {
            if (list != null && position >= 0 && position < list.size()) {
                return list.get(position);
            }
            return Optional.empty();
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
            final Component cpt;
            if (component == null) {
                cpt = LayoutScatter.getInstance(MainAbilitySlice.this).parse(ResourceTable.Layout_item_sample, null, false);
            } else {
                cpt = component;
            }
            String sampleItem = list.get(i);
            Text text = (Text) cpt.findComponentById(ResourceTable.Id_item_index);
            text.setText(sampleItem);
            return cpt;
        }
    }
}
